òɾۿûѧϰʹá
ԭַhttps://www.joinquant.com/post/13382

ԭһ˵ʽ鵽ԭĺ߽ۡ


ԭĲԴ£

'''
Ͷʳ
˹ǿͶʷΪͶʴڽ⡢ԳɳΪͶϡѡɷʽƫô͹ɣ
Ϊ쵼ҵƣԼʵʱʵĹ˾ӹ˾ֽҲǿȶɳҪ
ֵڵ50Ԫ
õĲṹ
ϸߵĹɶȨ汨ꡣ
ӵҳֽ
ȶӪճɳʡ
ڱȽָӯ౨ʡ
'''

import pandas as pd
import numpy as np
import jqdata
# ʼ趨׼ȵ
def initialize(context):
    # 趨300Ϊ׼
    set_benchmark('000300.XSHG')
    # ̬Ȩģʽ(ʵ۸)
    set_option('use_real_price', True)
    # ݵ־ log.info()
    log.info('ʼʼȫֻһ')
    # ˵orderϵAPIıerror͵log
    # log.set_level('order', 'error')
    #Բ
    #ĹƱб
    g.buy_list = []
    ### Ʊ趨 ###
    # ƱÿʽʱǣʱӶ֮ʱӶ֮ǧ֮һӡ˰, ÿʽӶͿ5Ǯ
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    # ÿµ5սв
    # ǰ
    run_monthly(before_market_open,5,time='before_open', reference_security='000300.XSHG') 
    # ʱ
    run_monthly(market_open,5,time='open', reference_security='000300.XSHG')
    
## ǰк     
def before_market_open(context):
    #ȡҪĹƱб
    temp_list = get_stock_list(context)

    #ȡĹƱб
    temp_list = get_stock_list(context)
    log.info('ĹƱ%sֻ'%len(temp_list))
    #ֵ
    g.buy_list = get_check_stocks_sort(context,temp_list)

## ʱк
def market_open(context):
    #беĹƱ
    sell(context,g.buy_list)
    #벻ڳֲеĹƱҪĹƱƽʽ
    buy(context,g.buy_list)
#׺ - 
def buy(context, buy_lists):
    # ȡյ buy_lists б
    # Ʊ
    if len(buy_lists)>0:
        #ʽ
        cash = context.portfolio.available_cash/(len(buy_lists)*1.0)
        # 
        for s in buy_lists:
            order_value(s,cash)
       
# ׺ - 
def sell(context, buy_lists):
    # ȡ sell_lists б
    hold_stock = context.portfolio.positions.keys()
    for s in hold_stock:
        #беĹƱ
        if s not in buy_lists:
            order_target_value(s,0)   

#ֵ   
#ӴС
def get_check_stocks_sort(context,check_out_lists):
    df = get_fundamentals(query(valuation.circulating_cap,valuation.pe_ratio,valuation.code).filter(valuation.code.in_(check_out_lists)),date=context.previous_date)
    #ascֵΪ0ӴС
    df = df.sort('circulating_cap',ascending=0)
    out_lists = list(df['code'].values)
    return out_lists
    
'''
1.ֵRгƽֵ*1.0
2.һʨRгƽֵʲϼ/ծϼƣ
3.ļɶȨ汨ʣroeRгƽֵ
4.ֽΪֵcash_flow.net_operate_cash_flow - cash_flow.net_invest_cash_flow
5.ļӪճɳʽ6%30%    'IRYOY':indicator.inc_revenue_year_on_year, # Ӫҵͬ(%)
6.ļӯɳʽ8%50%(epsֵ)
'''
def get_stock_list(context):
    temp_list = list(get_all_securities(types=['stock']).index)    
    #޳ͣƹ
    all_data = get_current_data()
    temp_list = [stock for stock in temp_list if not all_data[stock].paused]
    #ȡڲ
    panel = get_data(temp_list,4)
    #1.ֵRгƽֵ*1.0
    df_mkt = panel.loc[['circulating_market_cap'],3,:]
    df_mkt = df_mkt[df_mkt['circulating_market_cap']>df_mkt['circulating_market_cap'].mean()]
    l1 = set(df_mkt.index)
    
    #2.һʨRгƽֵʲϼ/ծϼƣ
    df_cr = panel.loc[['total_current_assets','total_current_liability'],3,:]
    #滻ֵ
    df_cr = df_cr[df_cr['total_current_liability'] != 0]
    df_cr['cr'] = df_cr['total_current_assets']/df_cr['total_current_liability']
    df_cr_temp = df_cr[df_cr['cr']>df_cr['cr'].mean()]
    l2 = set(df_cr_temp.index)

    #3.ļɶȨ汨ʣroeRгƽֵ
    l3 = {}
    for i in range(4):
        roe_mean = panel.loc['roe',i,:].mean()
        df_3 = panel.iloc[:,i,:]
        df_temp_3 = df_3[df_3['roe']>roe_mean]
        if i == 0:    
            l3 = set(df_temp_3.index)
        else:
            l_temp = df_temp_3.index
            l3 = l3 & set(l_temp)
    l3 = set(l3)

    #4.ֽΪֵcash_flow.net_operate_cash_flow - cash_flow.net_invest_cash_flow
    y = context.current_dt.year
    l4 = {}
    for i in range(1,6):
        df = get_fundamentals(query(cash_flow.code,cash_flow.statDate,cash_flow.net_operate_cash_flow , \
                                    cash_flow.net_invest_cash_flow),statDate=str(y-i))
        if len(df) != 0:
            df['FCF'] = df['net_operate_cash_flow']-df['net_invest_cash_flow']
            df = df[df['FCF']>0]
            l_temp = df['code'].values
            if len(l4) != 0:
                l4 = set(l4) & set(l_temp)
            l4 = l_temp
        else:
            continue
    l4 = set(l4)
    #print 'test'
    #print l4
    #5.ļӪճɳʽ6%30%    'IRYOY':indicator.inc_revenue_year_on_year, # Ӫҵͬ(%)
    l5 = {}
    for i in range(4):
        df_5 = panel.iloc[:,i,:]
        df_temp_5 = df_5[(df_5['inc_revenue_year_on_year']>6) & (df_5['inc_revenue_year_on_year']<30)]
        if i == 0:    
            l5 = set(df_temp_5.index)
        else:
            l_temp = df_temp_5.index
            l5 = l5 & set(l_temp)
    l5 = set(l5)
    
    #6.ļӯɳʽ8%50%(epsֵ)
    l6 = {}
    for i in range(4):
        df_6 = panel.iloc[:,i,:]
        df_temp = df_6[(df_6['eps']>0.08) & (df_6['eps']<0.5)]
        if i == 0:    
            l6 = set(df_temp.index)
        else:
            l_temp = df_temp.index
            l6 = l6 & set(l_temp)
    l6 = set(l6)
    
    return list(l1 & l2 &l3 & l4 & l5 & l6)
    
#ȥֵλ  
def winsorize(se):
    q = se.quantile([0.025, 0.975])
    if isinstance(q, pd.Series) and len(q) == 2:
        se[se < q.iloc[0]] = q.iloc[0]
        se[se > q.iloc[1]] = q.iloc[1]
    return se
    
#ȡڲ
def get_data(pool, periods):
    q = query(valuation.code, income.statDate, income.pubDate).filter(valuation.code.in_(pool))
    df = get_fundamentals(q)
    df.index = df.code
    stat_dates = set(df.statDate)
    stat_date_stocks = { sd:[stock for stock in df.index if df['statDate'][stock]==sd] for sd in stat_dates }

    def quarter_push(quarter):
        if quarter[-1]!='1':
            return quarter[:-1]+str(int(quarter[-1])-1)
        else:
            return str(int(quarter[:4])-1)+'q4'

    q = query(valuation.code,valuation.code,valuation.circulating_market_cap,balance.total_current_assets,balance.total_current_liability,\
    indicator.roe,cash_flow.net_operate_cash_flow,cash_flow.net_invest_cash_flow,indicator.inc_revenue_year_on_year,indicator.eps
              )

    stat_date_panels = { sd:None for sd in stat_dates }

    for sd in stat_dates:
        quarters = [sd[:4]+'q'+str(int(sd[5:7])/3)]
        for i in range(periods-1):
            quarters.append(quarter_push(quarters[-1]))
        nq = q.filter(valuation.code.in_(stat_date_stocks[sd]))
        pre_panel = { quarter:get_fundamentals(nq, statDate = quarter) for quarter in quarters }
        for thing in pre_panel.values():
            thing.index = thing.code.values
        panel = pd.Panel(pre_panel)
        panel.items = range(len(quarters))
        stat_date_panels[sd] = panel.transpose(2,0,1)

    final = pd.concat(stat_date_panels.values(), axis=2)

    return final.dropna(axis=2)
    
    
    